
#include <assert.h>

#include "c_Engine.h"
#include "c_Sprite.h"
#include "c_Texture.h"

wiigi::c_Texture*  wiigi::c_Sprite::m_CurrentTexture = (wiigi::c_Texture*)0;

wiigi::c_Sprite::c_Sprite( void )
:
   m_Texture( 0 ),
   m_Rotation( 0.0f ),
   m_Position( ),
   m_Scale( 1.0f, 1.0f ),
   m_Colour( 0xFFFFFFFF ),
   m_CurrentFrame( 0 ),
   m_FrameCnt( 0 ),
   m_FrameSize( ),
   m_Frames( 0 )
  
{
   return;
}

wiigi::c_Sprite::~c_Sprite( void )
{
   
   return;
}

/**
 * creates a sprite that covers the whole of the texture
 */
wiigi::e_Status wiigi::c_Sprite::init( 
   c_Texture* Texture
)
{
   e_Status Status( d_StatusUnkown );
   
   
   assert( 0 != Texture );
   m_Texture = Texture;
         
   m_FrameCnt = 1;
   
   m_Frames = new c_Texture::s_2D_TextCoords[ m_FrameCnt ];
   assert( 0 != m_Frames );
   if( 0 != m_Frames )
   {
      m_Texture->getFullFrame( m_Frames[ 0 ] );
      
      m_FrameSize.setValues( 0, 0, (f32)m_Texture->getWidth(), (f32)m_Texture->getHeight() );
      
      setCurrentFame( 0 );
      Status = d_StatusOK;
   }
   else
   {
      Status = d_StatusNoMemory;
   }
   
   assert( d_StatusUnkown != Status );
   return Status;
}

/**
 * creates a sprite that covers a sub rect of the texture
 */
wiigi::e_Status wiigi::c_Sprite::init( 
   c_Texture*       Texture,
   c_u32Rect& FrameSize
)
{
   e_Status Status( d_StatusUnkown );
   
   
   assert( 0 != Texture );
   m_Texture = Texture;
         
   m_FrameCnt = 1;
   
   m_Frames = new c_Texture::s_2D_TextCoords[ m_FrameCnt ];
   assert( 0 != m_Frames );
   if( 0 != m_Frames )
   {
      m_Texture->getSubFrame( m_Frames[ 0 ], FrameSize );
      
      m_FrameSize = FrameSize;
      
      setCurrentFame( 0 );
      Status = d_StatusOK;
   }
   else
   {
      Status = d_StatusNoMemory;
   }
   
   assert( d_StatusUnkown != Status );
   return Status;
}

/**
 * creates multi frames that cover the texture
 */
wiigi::e_Status wiigi::c_Sprite::init( 
   c_Texture* Texture,
   c_u32Rect& FrameSize,
   u32        FrameCnt
)
{
   e_Status Status( d_StatusUnkown );
   
   
   assert( 0 != Texture );
   m_Texture = Texture;
         
   m_FrameCnt = FrameCnt;
   
   m_Frames = new c_Texture::s_2D_TextCoords[ m_FrameCnt ];
   assert( 0 != m_Frames );
   if( 0 != m_Frames )
   {
      for( u32 Idx = 0; Idx < m_FrameCnt; Idx++ )
      {
         m_Texture->getSubFrame( m_Frames[ Idx ], Idx, FrameSize );
      }
      
      m_FrameSize = FrameSize;
      
      setCurrentFame( 0 );
      Status = d_StatusOK;
   }
   else
   {
      Status = d_StatusNoMemory;
   }
   
   assert( d_StatusUnkown != Status );
   return Status;
}

wiigi::e_Status wiigi::c_Sprite::draw( void )
{
   c_Texture* Texture;
   Texture = getTexture();
   if( Texture != m_CurrentTexture )
   {
      Texture->setAsCurrent();
      m_CurrentTexture = Texture;
   }
   
   GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
   GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
   
   Mtx m, m1, m2, mv;
   
   c_Texture::s_2D_TextCoords& CurrentFrame = m_Frames[ getCurrentFrame() ];
   
   const f32 width  = (f32)m_FrameSize.getWidth()  * 0.5f;
   const f32 height = (f32)m_FrameSize.getHeight() * 0.5f;
   guMtxIdentity (m1);
   guMtxScaleApply(m1, m1, (f32)m_Scale.getX(), (f32)m_Scale.getY(), 1.0);
   Vector axis = (Vector) {0, 0, 1 };
   guMtxRotAxisDeg (m2, &axis, (f32)m_Rotation);
   guMtxConcat(m2, m1, m);
   
   //guMtxTransApply(m, m, m_Position.getX() + width, m_Position.getY() + height, 0);
   guMtxTransApply(m, m, m_Position.getX() , m_Position.getY() , 0);
   guMtxConcat (c_Engine::m_GXmodelView2D, m, mv);
   GX_LoadPosMtxImm (mv, GX_PNMTX0);
   
   GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
   
   GX_Position3f32(-width, -height, 0);
   GX_Color1u32(m_Colour);
   GX_TexCoord2f32(CurrentFrame.s1, CurrentFrame.t1);
   
   GX_Position3f32(width, -height, 0);
   GX_Color1u32(m_Colour);
   GX_TexCoord2f32(CurrentFrame.s2, CurrentFrame.t1);
   
   GX_Position3f32(width, height, 0);
   GX_Color1u32(m_Colour);
   GX_TexCoord2f32(CurrentFrame.s2, CurrentFrame.t2);
   
   GX_Position3f32(-width, height, 0);
   GX_Color1u32(m_Colour);
   GX_TexCoord2f32(CurrentFrame.s1, CurrentFrame.t2);
   
   GX_End();
   
   GX_LoadPosMtxImm (c_Engine::m_GXmodelView2D, GX_PNMTX0);
   
   GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
   GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
   
   return d_StatusOK;
}

bool wiigi::c_Sprite::isVisible( 
   const c_f32Rect& ScreenArea
) const
{
   return true;
}

